/// -----------------------------------------------------------------------------------------------------------
/// Module      :  SalesForceWCFAdapterMetadataBrowseHandler.cs
/// Description :  This class is used while performing a connection-based browse for metadata from the target system.
/// -----------------------------------------------------------------------------------------------------------

#region Using Directives

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.ServiceModel.Channels;
using Microsoft.ServiceModel.Channels.Common;
using WCFLOBTalk.SalesForceWCF.Helpers;

#endregion

namespace WCFLOBTalk.SalesForceWCF
{
    public class SalesForceWCFAdapterMetadataBrowseHandler : SalesForceWCFAdapterHandlerBase, IMetadataBrowseHandler
    {

        // cache the connection
        private SalesForceWCFAdapterConnection conn = null;


        /// <summary>
        /// Initializes a new instance of the SalesForceWCFAdapterMetadataBrowseHandler class
        /// </summary>
        public SalesForceWCFAdapterMetadataBrowseHandler(SalesForceWCFAdapterConnection connection
            , MetadataLookup metadataLookup)
            : base(connection, metadataLookup)
        {
            this.conn = connection;
        }

        #region IMetadataBrowseHandler Members

        private MetadataRetrievalNode CreateNode(string id, string display, string descrtiption, bool isOperation) {
            MetadataRetrievalNode node = new MetadataRetrievalNode(id);
            node.NodeId = id;
            node.DisplayName = display;
            node.Description = descrtiption;
            if (id.Contains("get"))
            {
                node.Direction = MetadataRetrievalNodeDirections.Outbound;
            }
            else {
                if (id.Contains("set"))
                {
                    node.Direction = MetadataRetrievalNodeDirections.Inbound;
                }
                else
                {
                    node.Direction = MetadataRetrievalNodeDirections.Inbound | MetadataRetrievalNodeDirections.Outbound;
                }
            }
            node.IsOperation = isOperation;

            return node; 
        }


        /// <summary>
        /// Retrieves an array of MetadataRetrievalNodes from the target system.
        /// The browse will return nodes starting from the childStartIndex in the path provided in absoluteName, and the number of nodes returned is limited by maxChildNodes.
        /// The method should complete within the specified timespan or throw a timeout exception.
        /// If absoluteName is null or an empty string, return nodes starting from the root + childStartIndex.
        /// If childStartIndex is zero, then return starting at the node indicated by absoluteName (or the root node if absoluteName is null or empty).
        /// </summary>
        public MetadataRetrievalNode[] Browse(string nodeId
            , int childStartIndex
            , int maxChildNodes, TimeSpan timeout)
        {
            //
            //TODO: Implement the metadata browse on the target system.
            //

            // handle connection stuff better here!

            SFMetadata sfm = new SFMetadata();
            sfm = SFHelper.RetrieveMetadata(this.conn.ServiceInstance);

            MetadataRetrievalNode[] retNodes = new MetadataRetrievalNode[] { };

            if (MetadataRetrievalNode.Root.NodeId.CompareTo(nodeId) == 0)
            {
                MetadataRetrievalNode objCat = CreateNode("ObjectsCategory","Objects","Objects in SalesForce", false);
                MetadataRetrievalNode pkgCat = CreateNode("PackagesCategory","Packages","Code packages in SalesForce", false);

                return new MetadataRetrievalNode[] { objCat };

            }
            else {
                switch(nodeId) {
                    case "ObjectsCategory": 

                        List<MetadataRetrievalNode> col = new List<MetadataRetrievalNode>();
                        
                        foreach(SFObjectType so in sfm.Types) {
                            col.Add(CreateNode("Types/" + so.Name, so.Name, "Object type " + so.Name, false));    
                        }

                        return col.ToArray();

                        break;
                    case "PackagesCategory": 

                        break;

                }

            }


            // handle the types nodes here
            if (nodeId.Contains("Types/"))
            {
                string typeName = nodeId.Replace("Types/","");

                List<MetadataRetrievalNode> col = new List<MetadataRetrievalNode>();

                SFObjectType q = sfm.Types.Find(c => c.Name == typeName);

                foreach (string mi in q.Methods) 
                {
                    col.Add(CreateNode("Methods/" + typeName + "/" + mi, "Method Name " + mi, "", true));
                }

                return col.ToArray();
            }

            return retNodes;
        }

        #endregion IMetadataBrowseHandler Members
    }
}
